#pragma once 

#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#define DEFAULT 8081
#define BACKLOG 5

class TcpServer{
  private:
    int listen_sockfd;//listen listen_sockfd
    int port;
    //std::string ip;
  public:
    TcpServer(int _port = DEFAULT):listen_sockfd(-1), port(_port)//, ip(_ip)
    {}
    bool InitTcpServer()
    {
      listen_sockfd = socket(AF_INET, SOCK_STREAM, 0);
      if(listen_sockfd == -1){
        std::cerr << "socket error" << std::endl;
        return false;
      }

      struct sockaddr_in local;
      memset(&local, 0, sizeof(local));
      local.sin_family = AF_INET;
      local.sin_port = htons(port);
      local.sin_addr.s_addr = INADDR_ANY;
      //local.sin_addr.s_addr = inet_addr(ip.c_str());
      socklen_t len = sizeof(local);
      if(bind(listen_sockfd, (struct sockaddr*)&local, len) == -1){
        std::cerr << "bind error" << std::endl;
        return false;
      } 
      
      if(listen(listen_sockfd, BACKLOG) == -1){
        std::cerr << "listen error" << std::endl;
        return false;
      } 
        
      //接听成功
      std::cout << "listen succeed......" << std::endl;
      return true;
    }
    void Loop()
    {
#define SIZE 128
      struct sockaddr_in peer;
      while(true){
        socklen_t len = sizeof(peer);
        int sockfd = accept(listen_sockfd, (struct sockaddr*)&peer, &len);
        if(sockfd == -1){
          std::cerr << "accept error" << std::endl;
          continue;
        }

        std::string _ip = inet_ntoa(peer.sin_addr);
        uint16_t _port = ntohs(port);
        std::cout << "get a new link...[" << _ip << "]: " << _port << std::endl;

        Service(sockfd, _ip, _port);
      }
    }
    void Service(int sockfd, const std::string& _ip, const uint16_t& _port)
    {
        char buffer[SIZE];
        while(true){
            ssize_t size = read(sockfd, buffer, sizeof(buffer) - 1);
            if(size == -1){
                std::cerr << sockfd <<"read error" << std::endl;
                break;
            }
            else if(size == 0){
                std::cout << _ip << ":" <<_port << " close"<< std::endl;
                break;
            }
            else{
                buffer[size] = 0;
                std::cout << _ip << ":" <<_port << "# " << buffer << std::endl;
            }
        }
        close(sockfd);
        std::cout << "service done" << std::endl;
    }
    ~TcpServer()
    {
      if(listen_sockfd != -1) close(listen_sockfd);
    }
};
